﻿using System;
using System.Collections.Generic;
using Microsoft.Practices.Prism;
using Microsoft.Practices.Prism.Regions;
using Microsoft.Practices.ServiceLocation;

namespace UnityExtensions
{
    /// <summary>
    /// Defines a registry for the content of the regions used on View Discovery composition.
    /// </summary>
    public class ScopedRegionViewRegistry : IScopedRegionViewRegistry
    {
        private readonly ListDictionary<string, Func<IRegion, IServiceLocator, object>> _registeredContent = new ListDictionary<string, Func<IRegion, IServiceLocator, object>>();

        public event EventHandler<ViewRegisteredEventArgs> ContentRegistered;

        public void RegisterViewWithRegion(string regionName, Func<IRegion, IServiceLocator, object> getContentDelegate)
        {
            _registeredContent.Add(regionName, getContentDelegate);
            OnContentRegistered(new ViewRegisteredEventArgs(regionName, getContentDelegate));
        }

        public void RegisterViewWithRegion(string regionName, Type viewType)
        {
            RegisterViewWithRegion(regionName, (region, serviceLocator) => GetViewForRegion(region, serviceLocator, viewType));
        }

        public IEnumerable<Func<IRegion, IServiceLocator, object>> GetContents(string regionName)
        {
            return _registeredContent[regionName];
        }

        /// <summary>
        /// Default delegate used to resolve a view for a region.
        /// </summary>
        /// <param name="region">Region being populated.</param>
        /// <param name="serviceLocator">Locally scoped service locator.</param>
        /// <param name="viewType">The type of view registered.</param>
        /// <returns>Constructed view object.</returns>
        protected virtual object GetViewForRegion(IRegion region, IServiceLocator serviceLocator, Type viewType)
        {
            return serviceLocator.GetInstance(viewType);
        }

        /// <summary>
        /// Raises the <see cref="ContentRegistered"/> event.
        /// </summary>
        /// <param name="e">Event arguments for the event.</param>
        protected virtual void OnContentRegistered(ViewRegisteredEventArgs e)
        {
            var handler = ContentRegistered;
            if (handler != null)
            {
                handler(this, e);
            }
        }
    }
}
